作为一名对自身职业充满热爱的Android工程师,C/C++的重要性不言而喻,以图镇楼,提醒自己~
1、基本路线
1.1、数据类型
1)一些基本类型可以使用一个或多个类型修饰符进行修饰:
- signed
- unsigned
- short
- long
2)typedef 声明
您可以使用 typedef 为一个已有的类型取一个新的名字。下面是使用 typedef 定义一个新类型的语法:
1 | typedef type newname; |
例如,下面的语句会告诉编译器,feet 是 int 的另一个名称:
1 | typedef int feet; |
上面的声明是完全合法的,它创建了一个整型变量 distance:
1.2、存储类
1) auto
声明变量时根据初始化表达式自动推断该变量的类型、
声明函数时函数返回值的占位符。
2) static
- 当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内;
3)extern
- extern 修饰符通常用于当有两个或多个文件共享相同的全局变量或函数的时候;
1.3、循环
1)for
- 一般情况下,C++ 程序员偏向于使用 for(;;) 结构来表示一个无限循环。
1.4、函数
1)函数声明
在函数声明中,参数的名称并不重要,只有参数的类型是必需的,比如如下两种声明等价:
1 | int max(int num1, int num2); |
1 | int max(int, int); |
2)函数参数
当调用函数时,有三种向函数传递参数的方式:
调用类型 | 描述 |
---|---|
传值调用 | 该方法把参数的实际值复制给函数的形式参数。在这种情况下,修改函数内的形式参数对实际参数没有影响。 |
指针调用 | 该方法把参数的地址复制给形式参数。在函数内,该地址用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。 |
引用调用 | 该方法把参数的引用复制给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。 |
3)参数的默认值
1 | int sum(int a, int b=20){ |
4)typedef函数指针
形式:typedef 返回类型 (*新类型)(参数表)
1 | typedef char (*PTRFUN)(int); |
1 |
|
5)C++ 11 Lambda表达式
1.5、数组
1)多维数组
1 |
|
2)初始化数组
1 | double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0}; |
1.6、字符串
C++ 提供了以下两种类型的字符串表示形式:
- C 风格字符串
- C++ 引入的 string 类类型
1)C 风格字符串
1 | char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; |
C++ 中有大量的函数用来操作以 null 结尾的字符串:
序号 | 函数 & 目的 |
---|---|
1 | strcpy(s1, s2):复制字符串 s2 到字符串 s1。 |
2 | strcat(s1, s2): 连接字符串 s2 到字符串 s1 的末尾。 |
3 | strlen(s1): 返回字符串 s1 的长度。 |
4 | strcmp(s1, s2): 如果 s1 和 s2 是相同的,则返回 0;如果 s1 |
5 | strchr(s1, ch): 返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。 |
6 | strstr(s1, s2): 返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。 |
1.7、指针
1)空指针
在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯;
1
2
3
4
5
6
7
8
9
10
11
12
using namespace std;
int main ()
{
int *ptr = NULL;
cout << "ptr 的值是 " << ptr ;
return 0;
}检查一个空指针,您可以使用 if 语句,如下所示:
1
2if(ptr) /* 如果 ptr 非空,则完成 */
if(!ptr) /* 如果 ptr 为空,则完成 */
2)指针的算术运算
1 | int main () |
3)指针 VS 数组
指针和数组在很多情况下是可以互换的;
修改 var 的值是非法的。这是因为 var 是一个指向数组开头的常量,不能作为左值。
1
2
3
4
5
6
7
8
9
10
11int main ()
{
int var[MAX] = {10, 100, 200};
for (int i = 0; i < MAX; i++)
{
*var = i; // 这是正确的语法
var++; // 这是不正确的
}
return 0;
}
4)指针数组
5)指向指针的指针
1 | int main () |
1.8、引用
1)引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字;
2)引用 vs 指针
引用很容易与指针混淆,它们之间有三个主要的不同:
- 不存在空引用。引用必须连接到一块合法的内存。
- 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
- 引用必须在创建时被初始化。指针可以在任何时间被初始化。
3)实例
1 | int main () |
1.9、类
1)拷贝构造函数
2)构造函数初始化列表
构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。
TODO:https://www.runoob.com/w3cnote/cpp-construct-function-initial-list.html
2、知识积累
2.1、静态库和动态库
- 在Linux中静态库是以 .a 为后缀的文件,共享库是以 .so为后缀的文件。
静态库和动态库的区别:
当程序与静态库连接时,源文件中所有引用的库函数所对应的目标文件和源文件的目标文件会一起链接起来生成可执行文件。这就会导致最终生成的可执行代码量相对变多,相当于编译器将代码补充完整了,这样运行起来相对就快些。缺点: 占用磁盘和内存空间. 静态库会被添加到和它连接的每个程序中, 而且这些程序运行时, 都会被加载到内存中. 无形中又多消耗了更多的内存空间.
当程序与共享库连接时,只包含它需要的函数的引用表,而不是所有的函数代码,只有在程序执行时, 那些需要的函数代码才被拷贝到内存中。这样就使可执行文件比较小, 节省磁盘空间,更进一步,操作系统使用虚拟内存,使得一份共享库驻留在内存中被多个程序使用,也同时节约了内存。缺点:不过由于运行时要去链接库会花费一定的时间,执行速度相对会慢一些。
- 一个程序编好后,有时需要做一些修改和优化,如果我们要修改的刚好是库函数的话,在接口不变的前提下,使用共享库的程序只需要将共享库重新编译就可以了(增量更新),而使用静态库的程序则需要将静态库重新编译好后,将程序再重新编译一遍(全量更新)。
2.2、std::lock_guard
TODO:https://www.jianshu.com/p/681f553fa4ab
2.3、std::make_unique和std::make_shared
2.4、C++类型转换之reinterpret_cast
TODO:https://zhuanlan.zhihu.com/p/33040213